package com.shteo.crmd.goods.config;

import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.jdbc.ShardingDataSource;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.shteo.crmd.goods.shard.DBSharding;
import com.shteo.crmd.goods.shard.TableSharding;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.*;

@Configuration
@EnableTransactionManagement
@MapperScan("com.shteo.crmd.goods.dao")
public class DBConfig {

	private Logger logger = Logger.getLogger(DBConfig.class);

	@Bean
	public DataSourceRule dataSourceRule(){
		return new DataSourceRule(createDataSource());
	}

	@Bean
	public DBSharding dbSharding(){
		return new DBSharding();
	}

	@Bean
	public TableSharding tableSharding(){
		return new TableSharding();
	}

	@Bean
	public DatabaseShardingStrategy databaseShardingStrategy(){
		return new DatabaseShardingStrategy("id",dbSharding());
	}

	@Bean
	public TableShardingStrategy tableShardingStrategy(){
		return new TableShardingStrategy("id",tableSharding());
	}

	@Bean
	public ShardingRule shardingRule(){
		//表分库分表规则
		TableRule goodsTr = TableRule.builder("goods")
				.actualTables(Arrays.asList("goods_0","goods_1"))
				.dataSourceRule(dataSourceRule())
				.build();
		ShardingRule shardingRule = ShardingRule.builder()
				.dataSourceRule(dataSourceRule())
				.tableRules(Arrays.asList(goodsTr))
				.databaseShardingStrategy(databaseShardingStrategy())
				.tableShardingStrategy(tableShardingStrategy())
				.build();
		return shardingRule;
	}

	@Bean
	public ShardingDataSource shardingDataSource(){
		return new ShardingDataSource(shardingRule());
	}

	@Bean(name = "sqlSessionFactory")
	public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(shardingDataSource());
		sqlSessionFactoryBean.setTypeAliasesPackage("com.shteo.crmd.model");
		PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:com/shteo/crmd/goods/dao/**/*.xml"));
		// 增加拦截器插件
		PageHelper pageHelper = new PageHelper();
		Properties properties = new Properties();
		properties.put("dialect","mysql");
		properties.put("reasonable",true);
		properties.put("offsetAsPageNum",true);
		properties.put("rowBoundsWithCount",true);
		properties.put("pageSizeZero",true);
		pageHelper.setProperties(properties);
		sqlSessionFactoryBean.setPlugins(new Interceptor[] { pageHelper });

		return sqlSessionFactoryBean.getObject();
	}

	@Primary
	@Bean(destroyMethod = "close")
	@ConfigurationProperties(prefix = "datasource0.druid")
	public DataSource druidDataSource0(){
		logger.info("Goods ds0 Initial...");
		return new BasicDataSource();
	}

	@Bean(destroyMethod = "close")
	@ConfigurationProperties(prefix = "datasource1.druid")
	public DataSource druidDataSource1(){
		logger.info("Goods ds1 Initial...");
		return new BasicDataSource();
	}

	/**
	 * 创建多个数据源
	 * @return
	 */
	private Map<String,DataSource> createDataSource(){
		Map<String,DataSource> dataSourceMap = Maps.newConcurrentMap();
		dataSourceMap.put("ds_0",druidDataSource0());
		dataSourceMap.put("ds_1",druidDataSource1());
		return dataSourceMap;
	}


}
